#include "StackMemoryManager.h"

StackMemoryManager::StackMemoryManager( int nSizeInBytes, int nByteAlignment ) {
	stack = new StackMemorySystem(nSizeInBytes, nByteAlignment);
	//markers[stack->LOWER].reserve(nSizeInBytes/nByteAlignment);
	//markers[stack->UPPER].reserve(nSizeInBytes/nByteAlignment);
}

StackMemoryManager::~StackMemoryManager() {
	delete stack;
}

void* StackMemoryManager::alloc(int nBytes, unsigned& id, bool nHeapNum = false) {
#ifdef DEBUG
	printf("Allocate memory (%s: %d bytes)\n", nHeapNum?"UPPER":"LOWER", nBytes);
#endif
	markers[nHeapNum].push_back(stack->getMarker(nHeapNum));
	void* ptr = stack->alloc(nBytes, nHeapNum);
	
	if( !ptr ) {
		printf("Unsufficient memory");
		id = 0;
	} else
		id = getId(nHeapNum);
	return ptr;	
}

unsigned StackMemoryManager::release(bool nHeapNum = false) {
#ifdef DEBUG
	printf("Release memory (%s)\n", nHeapNum?"UPPER":"LOWER");
#endif
	unsigned id = getId(nHeapNum);
	if( id ) {
		stack->freeToMarker(*(markers[nHeapNum].end()-1));
		markers[nHeapNum].pop_back();
	} else
		id = 0;
	return id;
}

unsigned StackMemoryManager::getId(bool nHeapNum = false) {
	unsigned id = markers[nHeapNum].size();
	return nHeapNum?2*id:2*id-1;
}

void StackMemoryManager::clean(bool nHeapNum) { 
#ifdef DEBUG
	printf("Clear memory from %s heap\n", nHeapNum?"UPPER":"LOWER");
#endif
	stack->freeAll(nHeapNum); 
}

void StackMemoryManager::clean() {
#ifdef DEBUG
	printf("Clear memory\n");
#endif
	stack->freeAll(); 
}

void StackMemoryManager::log() {
	printf("Stack capacity: \t%d\n", stack->getCapacity());
	printf("Stack used size: \t%d (UPPER: %d / LOWER: %d)\n", 
		stack->getUsedSize(), stack->getUsedSize(stack->UPPER), stack->getUsedSize(stack->LOWER));
	printf("Stack free size: \t%d\n", stack->getFreeSize());
	printf("Stack is empty: \t%s\n", stack->IsEmpty()?"YES":"NO");
	printf("Stack is full: \t\t%s\n", stack->IsFull()?"YES":"NO");
	printf("\n");
}